'use strict';
// Copyright 2014 Blueant Inc. All Rights Reserved.

/**
 * @fileoverview 玩家数据
 * @author sundbcn@gmail.com (sun debing)
 */

var _ = require('lodash');
var async = require('async');
var fs = require('fs');
var path = require('path');
var moment = require('moment');
// var timeEventType = require('../consts/timeEventType.js');
var configUtil = require('../util/configUtil.js');
var no_refresh = configUtil.load('game').no_refresh;

// 模块列表(角色相关)
var model_list = {};

// 预加载模块列表(包含数据刷新事件onRefreshData(self, cb)的模块)
var pre_load_keys = [];

// 每日刷新模块列表(包含每日刷新事件onDailyRefresh(self, cb)的模块)
var daily_refresh_keys = [];

// 5点刷新模块列表(包含5点刷新事件onFiveRefresh(self, cb)的模块)
var five_refresh_keys = [];

// 是否正在生成预加载模块列表（如果正在生成，说明当前正在刷新数据，可以放弃本次刷新数据）
var making_pre_load_keys = false;

var loaded = false;

module.exports = function (role_id) {
    this.role_id = role_id;
};

var Player = module.exports;

/**
 * 获取角色id
 * @return {[type]} [description]
 */
Player.prototype.getRoleId = function () {
    return this.role_id;
};

/**
 * 刷新数据
 * @return {[type]} [description]
 */
Player.prototype.refreshData = function (next) {
    var self = this;
    if (!next) {
        next = function (err) {
            console.error(err);
        };
    }
    if (!!no_refresh) {
        return next();
    }

    async.waterfall(
        [
            function (cb) {
                // 生成预加载模块列表
                if (pre_load_keys.length === 0) {
                    if (!!making_pre_load_keys) {
                        // 正在生成预加载列表，说明当前正在刷新数据，可以放弃本次刷新数据
                        return next();
                    }
                    making_pre_load_keys = true;
                    _makePreloadModelList(cb);
                } else {
                    cb();
                }
            },
            function (cb) {
                // 每日刷新
                _dailyRefresh(self, cb);
            },
            function (cb) {
                // 5点刷新
                _fiveRefresh(self, cb);
            },
            function (cb) {
                // 定时刷新数据
                _refreshData(self, cb);
            }
        ],
        function (err) {
            next(err);
        }
    );
};

/**
 * 生成预加载列表
 */
var _makePreloadModelList = function (next) {
    _getKeys(function (err, model_keys) {
        _.forEach(model_keys, function (key) {
            var model_loader = _getModelLoader(key);
            if (!!model_loader) {
                if (!!model_loader.onRefreshData) {
                    pre_load_keys.push(key);
                }
                if (!!model_loader.onDailyRefresh) {
                    daily_refresh_keys.push(key);
                }
                if (!!model_loader.onFiveRefresh) {
                    five_refresh_keys.push(key);
                }
            }
        });
        // console.log('pre_load_keys:', pre_load_keys);
        // console.log('daily_refresh_keys:', daily_refresh_keys);
        // console.log('five_refresh_keys:', five_refresh_keys);
        next();
    });
};

/**
 * 每日新数据
 */
var _dailyRefresh = function (self, next) {
    var role_model;
    async.waterfall(
        [
            function (cb) {
                // 装入角色表
                self.getModel(['role'], cb);
            },
            function (cb) {
                role_model = self.role;
                if (moment().unix() < role_model.next_refresh_day) {
                    // 未到下一天
                    return next();
                }
                cb();
            },
            function (cb) {
                // 装入预加载模块
                async.each(daily_refresh_keys, function (key, callback) {
                    _getModel(self, key, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }
                    cb();
                });
            },
            function (cb) {
                // 刷新数据
                async.eachSeries(daily_refresh_keys, function (key, callback) {
                    var model_loader = model_list[key];
                    var model = self[key];
                    // console.log('---dailyRefresh():', key);
                    model_loader.onDailyRefresh(model, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }

                    role_model.next_refresh_day = moment().startOf('day').add(1, 'days').unix();
                    self.save(cb);
                });
            }
        ],
        function (err) {
            return next(err);
        }
    );
};

/**
 * 5点刷新
 */
var _fiveRefresh = function (self, next) {
    var role_model;
    async.waterfall(
        [
            function (cb) {
                // 装入角色表
                self.getModel(['role'], cb);
            },
            function (cb) {
                role_model = self.role;
                if (moment().unix() < role_model.next_five_refresh) {
                    // 未到下一个5点
                    return next();
                }
                cb();
            },
            function (cb) {
                // 装入5点刷新模块
                async.each(five_refresh_keys, function (key, callback) {
                    _getModel(self, key, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }
                    cb();
                });
            },
            function (cb) {
                // 刷新数据
                async.eachSeries(five_refresh_keys, function (key, callback) {
                    var model_loader = model_list[key];
                    var model = self[key];
                    // console.log('---dailyRefresh():', key);
                    model_loader.onFiveRefresh(model, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }

                    role_model.next_five_refresh = moment().startOf('day').add(29, 'h').unix();
                    self.save(cb);
                });
            }
        ],
        function (err) {
            return next(err);
        }
    );
};

/**
 * 定时刷新数据
 */
var _refreshData = function (self, next) {
    async.waterfall(
        [
            function (cb) {
                // 装入预加载模块
                async.each(pre_load_keys, function (key, callback) {
                    _getModel(self, key, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }
                    cb();
                });
            },
            function (cb) {
                // 刷新数据
                async.eachSeries(pre_load_keys, function (key, callback) {
                    var model_loader = model_list[key];
                    var model = self[key];
                    // console.log('---RefreshData():', key);
                    model_loader.onRefreshData(model, callback);
                }, function (err) {
                    if (!!err) {
                        return next(err);
                    }
                    self.save(cb);
                });
            }
        ],
        function (err) {
            return next(err);
        }
    );
};

// var event_to_model = {};
// 
// event_to_model[timeEventType.ACTIVITY] = 'activity';
// event_to_model[timeEventType.ARENA] = 'arena';
// event_to_model[timeEventType.BUILD] = 'build';
// event_to_model[timeEventType.EXPEDITION] = 'expedition';
// event_to_model[timeEventType.ROLE] = 'role';
// event_to_model[timeEventType.SMITHY] = 'smithy';
// event_to_model[timeEventType.TECH] = 'tech';
// event_to_model[timeEventType.HUNT] = 'hunt';
// 
// /**
//  * 采用事件表刷新数据
//  */
// var _newRefreshData = function (self, next) {
//     var reach_list = [];
//     async.waterfall(
//         [
//             function (cb) {
//                 _getModel(self, 'time_event', cb);
//             },
//             function (cb) {
//                 var time_event_model = self.time_event;
//                 if (time_event_model.event_list.length === 0) {
//                     return next();
//                 }
// 
//                 // 事件重排
//                 time_event_model.arrangeEvent();
// 
//                 // 取出到期事件列表
//                 var now_tm = moment().unix();
//                 _.forEach(time_event_model.event_list, function (evt) {
//                     if (evt.trigger_tm < now_tm) {
//                         return false;
//                     }
//                     var key = event_to_model[evt.event_id];
//                     reach_list.push(key);
//                     return true;
//                 });
// 
//                 if (reach_list.length === 0) {
//                     return next();
//                 }
//                 
//                 // 移除到期事件
//                 time_event_model.removeFrontEvent(reach_list.length);
// 
//                 cb();
//             },
//             function (cb) {
//                 // 装入数据
//                 async.eachSeries(reach_list, function (key, callback) {
//                     _getModel(self, key, callback);
//                 }, function (err) {
//                     if (!!err) {
//                         return next(err);
//                     }
//                     cb();
//                 });
//             },
//             function (cb) {
//                 // 执行定时刷新
//                 async.eachSeries(reach_list, function (key, callback) {
//                     var model_loader = model_list[key];
//                     var model = self[key];
//                     model_loader.onRefreshData(model, callback);
//                 }, function (err) {
//                     if (!!err) {
//                         return next(err);
//                     }
//                     self.save(cb);
//                 });
//             }
//         ],
//         function (err) {
//             return next(err);
//         }
//     );
// };

/**
 * 获取所有的Model
 * @param  {Function} cb [description]
 * @return {[type]}      [description]
 */
Player.prototype.getAllModel = function (cb) {
    var self = this;
    _getKeys(function (err, model_keys) {
        async.eachSeries(model_keys, function (key, callback) {
            // console.log('get model:', key);
            _getModel(self, key, callback);
        }, function (err) {
            cb();
        });
    });
};

/**
 * 取出模块列表
 * @param  {Function} cb [description]
 * @return {[type]}      [description]
 */
var _getKeys = function (cb) {
    if (!!loaded) {
        var keys = _.keys(model_list);
        return cb(null, keys);
    }

    fs.readdir(__dirname + '/../models/', function (err, files) {
        if (!!err) {
            console.error(err);
            return cb();
        }
        var keys = [];
        var suffix = 'Model.js';
        var suffix_len = suffix.length;
        files.forEach(function (file_name) {
            if (_isSkipFile(file_name)) {
                return true;
            }
            var name_len = file_name.length;
            if (name_len < suffix_len) {
                return true;
            }
            if (file_name.substr(name_len - suffix_len, suffix_len) !== suffix) {
                return true;
            }

            var key = file_name.substr(0, name_len - suffix_len);
            key = key.replace(/[A-Z]/g, function (ch) {
                return '_' + ch.toLowerCase();
            });
            keys.push(key);
        });

        loaded = true;
        cb(null, keys);
    });
};

var skip_list = [
    'battleRecordModel.js',
    'bossRecordModel.js',
    'cdkInfoModel.js',
    'cdkTypeModel.js',
    'copyRecordModel.js',
    'payRecordModel.js',
    'rebelRecordModel.js',
    'unionGroupModel.js',
    'userModel.js',
    'redPacketModel.js',
    'onlineUserCountModel.js',
    'globalBossModel.js',
    'unionBossModel.js'
];

var _isSkipFile = function (file_name) {
    var found = false;
    _.each(skip_list, function (check) {
        if (check === file_name) {
            found = true;
            return false;
        }
    });

    return found;
};

/**
 * 获取model
 * @param  {[type]}   model_key_list [description]
 * @param  {Function} cb             [description]
 * @return {[type]}                  [description]
 */
Player.prototype.getModel = function (model_key_list, cb) {
    var self = this;
    async.eachSeries(model_key_list, function (model_key, callback) {
        _getModel(self, model_key, callback);
    }, function (err) {
        cb();
    });
};

var first_push = ['role', 'pay'];

Player.prototype.push = function () {
    var self = this;
    var push_list = [];
    var first_map = {};
    _.each(first_push, function (model_key) {
        first_map[model_key] = 1;
        var model = self[model_key];
        if (!!model) {
            push_list.push(model);
        }
    });

    _.each(model_list, function (model_loader, model_key) {
        if (first_map[model_key]) {
            return true;
        }
        var model = self[model_key];
        if (!!model) {
            push_list.push(model);
        }
        return true;
    });

    _.each(push_list, function (model) {
        if (!!model.push) {
            model.push();
        }
    });
};

/**
 * 输出
 * @return {[type]} [description]
 */
Player.prototype.toJSON = function () {
    var self = this;
    var data = {};
    _.each(model_list, function (model_loader, model_key) {
        var model = self[model_key];
        if (!!model) {
            data[model_key] = model.toJSON();
        }
    });
    return data;
};

/**
 * 保存数据
 * @param  {Function} cb [description]
 * @return {[type]}      [description]
 */
Player.prototype.save = function (cb) {
    var self = this;
    var model_keys = _.keys(model_list);
    async.each(model_keys, function (model_key, callback) {
        var model = self[model_key];
        if (!!model && !!model.isModified()) {
            model.save(callback);
        } else {
            callback();
        }
    }, function (err) {
        if (!!cb) {
            cb(err);
        }
    });
};

/**
 * 获取单个model
 * @param  {[type]}   self      [description]
 * @param  {[type]}   model_key [description]
 * @param  {Function} cb        [description]
 * @return {[type]}             [description]
 */
var _getModel = function (self, model_key, cb) {
    var model_loader = model_list[model_key];
    if (!model_loader) {
        var model_file =
            model_key.replace(/_./g, function (str) {
                return str.substring(1).toUpperCase();
            });
        model_loader = require('../models/' + model_file + 'Model.js');
        if (!!model_loader) {
            model_list[model_key] = model_loader;
        } else {
            console.error('load model error: ' + model_file);
        }
    }
    if (!!self[model_key]) {
        return cb();
    }

    if (!model_loader) {
        return cb();
    }

    if (!model_loader.getByRoleId) {
        return cb();
    }

    model_loader.getByRoleId(self.role_id, function (err, model) {
        if (!!err) {
            return cb(err);
        }
        model.mgr = self;
        self[model_key] = model;
        return cb();
    });
};

/**
 * 获取模块加载器
 * @param  {[type]}   self      [description]
 * @param  {[type]}   model_key [description]
 * @return {[type]}             [description]
 */
var _getModelLoader = function (model_key) {
    var model_loader = model_list[model_key];
    if (!model_loader) {
        var model_file =
            model_key.replace(/_./g, function (str) {
                return str.substring(1).toUpperCase();
            });
        model_loader = require('../models/' + model_file + 'Model.js');
        if (!!model_loader) {
            model_list[model_key] = model_loader;
        } else {
            console.error('load model error: ' + model_file);
        }
    }
    return model_loader;
};
